package com.erdos.core.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.erdos.common.exception.GlobalRuntimeException;
import com.erdos.core.dao.EventDao;
import com.erdos.core.dao.FSMDao;
import com.erdos.core.dao.StateDao;
import com.erdos.core.dao.StateTransitionDao;
import com.erdos.core.entity.Event;
import com.erdos.core.entity.State;
import com.erdos.core.service.FSMService;

public class FSMServiceImpl implements FSMService{
	
	private EventDao eventDao;
	private StateDao stateDao;
	private StateTransitionDao stateTransitionDao;
	private FSMDao fsmDao;

	/**
	 * 查询startState下可用的事件集合
	 * @param startState
	 * @return List<Event>
	 * @author liujinsong
	 * @since  2008-8-5
	 */
	public List<Event> findAvaiableEvent(State startState) {
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("startStateSid", startState.getSid());
		return fsmDao.findEventsByTransitionParams(params);
	}

	/**
	 * 查询startState下可用的跃迁状态集合
	 * @param startState
	 * @return List<State>
	 * @author liujinsong
	 * @since  2008-8-6
	 */
	public List<State> findAvaiableState(State startState) {
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("startStateSid",startState.getSid());
		return fsmDao.findStatesByTransitionParams(params);
	}

	/**
	 * 通过事件代码查询事件对象
	 * @param eventId 事件代码
	 * @return event
	 * @author liujinsong
	 * @since  2008-8-8
	 */
	public Event findUniqueEvent(String eventId) {
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("eventId", eventId);
		return eventDao.findUniqueByParams(params);
	}

	/**
	 * 根据当前状态、传入事件及条件值，返回下一个跃迁状态
	 * @param startState 当前状态
	 * @param eventId 转换事件代码
	 * @param condition 判定条件值
	 * @return state
	 * @author liujinsong
	 * @since  2008-8-8
	 */
	public State processTransition(State startState, String eventId,
			Integer condition) {
		Map<String,Object> params=new HashMap<String, Object>();
		List<State> resultList = new ArrayList<State>();
		if(startState==null){
			params.put("startStateSidNull","true");
		}
		else{
			params.put("startStateSid", startState.getSid());
		}
		params.put("eventId", eventId);
		if(condition==null){
			params.put("transitionConditionNull","true");
			resultList = fsmDao.findStatesByTransitionParams(params);
			if(resultList==null || resultList.size()==0){
				return null;
			}
			else if(resultList.size()==1)
			{
			return resultList.get(0);	
			}
			else
			{
			throw new GlobalRuntimeException("error.code.transition.state.over",new String[]{"error.code.transition.state.over"});	
			}
		}
		else{
			params.put("transitionCondition", condition);
			
			  resultList = fsmDao.findStatesByTransitionParams(params);
			if(resultList==null || resultList.size()==0){
				params.remove("transitionCondition");
				params.put("transitionConditionNull","true");
				resultList = fsmDao.findStatesByTransitionParams(params);
				if(resultList==null || resultList.size()==0){
					return null;
				}
				else if(resultList.size()==1)
				{
				return resultList.get(0);	
				}
				else
				{
				throw new GlobalRuntimeException("error.code.transition.state.over",new String[]{"error.code.transition.state.over"});	
				}
			}
			else if(resultList.size()==1)
			{
			return resultList.get(0);	
			}
			else
			{
			throw new GlobalRuntimeException("error.code.transition.state.over",new String[]{"error.code.transition.state.over"});	
			}
			}
		}

	public EventDao getEventDao() {
		return eventDao;
	}

	public void setEventDao(EventDao eventDao) {
		this.eventDao = eventDao;
	}

	public StateDao getStateDao() {
		return stateDao;
	}

	public void setStateDao(StateDao stateDao) {
		this.stateDao = stateDao;
	}

	public StateTransitionDao getStateTransitionDao() {
		return stateTransitionDao;
	}

	public void setStateTransitionDao(StateTransitionDao stateTransitionDao) {
		this.stateTransitionDao = stateTransitionDao;
	}

	public FSMDao getFsmDao() {
		return fsmDao;
	}

	public void setFsmDao(FSMDao fsmDao) {
		this.fsmDao = fsmDao;
	}

	/* (non-Javadoc)
	 * @see com.hp.core.service.FSMService#findStartState(java.lang.String, java.lang.Integer)
	 */
	public State findStartState(String eventId, Integer condition) {
		return this.processTransition(null, eventId, condition);
	}
}
